package it.polimi.entitiesManagers;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import it.polimi.authentication.ejb.usermanagement.User;
import it.polimi.entities.Airport;
import it.polimi.entities.Attraction;
import it.polimi.entities.Flight;
import it.polimi.entities.Hotel;
import it.polimi.entities.Packet;
import it.polimi.entities.PacketAttraction;
import it.polimi.entities.PacketFlight;
import it.polimi.entities.PersonalizedPacket;
import it.polimi.entitiesDTO.PersonalizedPacketDTO;

@Stateless
public class PersonalizedPacketManagerBean implements PersonalizedPacketMgr {

	@PersistenceContext
	private EntityManager em;

	@Resource
	private EJBContext context;

	private int personalizedPacketID;

	@Override
	public void save(PersonalizedPacketDTO personalizedPacket, int packetID) {
		Packet packet = em.createNamedQuery(Packet.FIND_PACKET, Packet.class)
				.setParameter("id", packetID).getSingleResult();
		User employee = em.createNamedQuery(User.FIND_BY_MAIL, User.class)
				.setParameter("email", packet.getEmployee()).getSingleResult();
		User user = em.createNamedQuery(User.FIND_BY_MAIL, User.class)
				.setParameter("email", context.getCallerPrincipal().getName())
				.getSingleResult();
		PersonalizedPacket newPacket = new PersonalizedPacket(
				personalizedPacket, packet, user, employee);
		System.out.println(packet.getHotel().toString());
		newPacket.setHotel(packet.getHotel());
		em.persist(newPacket);
		setPersonalizedPacketID(newPacket.getPacket());
		registerFlight(packetID);
		registerAttraction(packetID);
	}

	@Override
	public void update(PersonalizedPacketDTO personalizedPacket) {
		// TODO Auto-generated method stub

	}

	@Override
	public PersonalizedPacketDTO getPersonalizedPacketDTO() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void registerFlight(int packet) {
		Packet pack = em.createNamedQuery(Packet.FIND_PACKET, Packet.class)
				.setParameter("id", packet).getSingleResult();
		PersonalizedPacket perspacket = em
				.createNamedQuery(PersonalizedPacket.FIND_PACKET,
						PersonalizedPacket.class)
				.setParameter("packet", personalizedPacketID).getSingleResult();
		List<Flight> packetFlights = new ArrayList<Flight>();
		List<PacketFlight> packf = pack.getPacketFlights();
		for (PacketFlight pf : packf) {
			packetFlights.add(pf.getFlight());
			System.out.println(pf.getFlight().toString());
		}
		for (Flight f : packetFlights) {
			PacketFlight p = new PacketFlight(perspacket, f);
			em.persist(p);
			perspacket.addPacketFlight(p);
		}
		/*
		 * PacketFlight pf1 = new PacketFlight(); PacketFlight pf2 = new
		 * PacketFlight(); pf1.setFlight(pack.getPacketFlight(0).getFlight());
		 * pf2.setFlight(pack.getPacketFlight(1).getFlight());
		 * pf1.setPacket(null); pf1.setPersonalizedPacket(perspacket);
		 * pf2.setPacket(null); pf2.setPersonalizedPacket(perspacket);
		 * em.persist(pf1); em.persist(pf2);
		 */
	}

	@Override
	public void registerAttraction(int packet) {
		Packet pack = em.createNamedQuery(Packet.FIND_PACKET, Packet.class)
				.setParameter("id", packet).getSingleResult();
		PersonalizedPacket perspacket = em
				.createNamedQuery(PersonalizedPacket.FIND_PACKET,
						PersonalizedPacket.class)
				.setParameter("packet", personalizedPacketID).getSingleResult();
		List<Attraction> packetAttractions = new ArrayList<Attraction>();
		List<PacketAttraction> packa = pack.getPacketAttractions();
		for (PacketAttraction pa : packa) {
			packetAttractions.add(pa.getAttractionBean());
			System.out.println(pa.getAttractionBean().toString());
		}
		for (Attraction a : packetAttractions) {
			PacketAttraction p = new PacketAttraction(perspacket, a);
			em.persist(p);
			perspacket.addPacketAttraction(p);
		}
	}

	@Override
	public void changeHotel(int persPackID, int hotelID) {
		PersonalizedPacket pers = em
				.createNamedQuery(PersonalizedPacket.FIND_PACKET,
						PersonalizedPacket.class)
				.setParameter("packet", persPackID).getSingleResult();
		Hotel hotel = em.createNamedQuery(Hotel.FIND_BY_ID, Hotel.class)
				.setParameter("id", hotelID).getSingleResult();
		pers.setHotel(hotel);
	}
	
	@Override
	public void changeFlights(int persPackID, int departureFlight, int returnFlight){
		PersonalizedPacket pers = em.createNamedQuery(PersonalizedPacket.FIND_PACKET,PersonalizedPacket.class).setParameter("packet", persPackID).getSingleResult();
		List <PacketFlight> pFlights = pers.getPacketFlights();
		for(PacketFlight pf: pFlights)
			if (pf.getPacket() == null) em.remove(pf);
		pFlights.clear();
		Flight flight1 = em.createNamedQuery(Flight.FIND_FLIGHT, Flight.class).setParameter("id", departureFlight).getSingleResult();
		Flight flight2 = em.createNamedQuery(Flight.FIND_FLIGHT, Flight.class).setParameter("id", returnFlight).getSingleResult();
		PacketFlight pf1 = new PacketFlight(pers, flight1);
		em.persist(pf1);
		pers.addPacketFlight(pf1);
		PacketFlight pf2 = new PacketFlight(pers, flight2);
		em.persist(pf2);
		pers.addPacketFlight(pf2);
	}

	@Override
	public void addAttraction(int persPackID, int attractionID) {
		PersonalizedPacket pers = em
				.createNamedQuery(PersonalizedPacket.FIND_PACKET,
						PersonalizedPacket.class)
				.setParameter("packet", persPackID).getSingleResult();
		Attraction attraction = em
				.createNamedQuery(Attraction.FIND_ATTRACTION, Attraction.class)
				.setParameter("id", attractionID).getSingleResult();
		List<PacketAttraction> attractionList = pers.getPacketAttractions();
		boolean alreadyIn = false;
		for (PacketAttraction a : attractionList) {
			if (a.getAttractionBean() == attraction&& a.getPacketBean()==null)
				alreadyIn = true;
		}
		if (!alreadyIn) {
			PacketAttraction p = new PacketAttraction(pers, attraction);
			em.persist(p);
			pers.addPacketAttraction(p);
		}
	}

	@Override
	public void removeAttraction(int persPackID, int attractionID) {
		PersonalizedPacket pers = em.createNamedQuery(PersonalizedPacket.FIND_PACKET,PersonalizedPacket.class).setParameter("packet",persPackID).getSingleResult();
		Attraction attraction = em.createNamedQuery(Attraction.FIND_ATTRACTION, Attraction.class).setParameter("id", attractionID).getSingleResult();
		List<PacketAttraction> attractionList = pers.getPacketAttractions();
		boolean isIn = false;
		PacketAttraction toRemove = new PacketAttraction();
		for (PacketAttraction a : attractionList) {
			if (a.getAttractionBean() == attraction && a.getPacketBean()== null){
				isIn = true;
				toRemove = a;}
		}
		if (isIn){
			pers.removePacketAttraction(toRemove);
			em.remove(toRemove);
		}
	}

	public int getPersonalizedPacketID() {
		return personalizedPacketID;
	}

	public void setPersonalizedPacketID(int personalizedPacketID) {
		this.personalizedPacketID = personalizedPacketID;
	}

	public PersonalizedPacket getPersonalizedPacket(int id) {
		return em
				.createNamedQuery(PersonalizedPacket.FIND_PACKET,
						PersonalizedPacket.class).setParameter("packet", id)
				.getSingleResult();
	}
	
	@Override
	public List<String> getAlternativeHotels(int id) {
		List<String> someHotel= new ArrayList<String>();
		PersonalizedPacket pers = getPersonalizedPacket(id);
		for(Hotel h: hotelByCity(pers.getCity()))
			someHotel.add(h.toString());
		return someHotel;
	}

	private List<Hotel> hotelByCity(String city){
		return em.createNamedQuery(Hotel.FIND_BY_CITY, Hotel.class).setParameter("city", city).getResultList();
	} 
	
	@Override
	public List<Integer> fillMyPackets(){
		String id = context.getCallerPrincipal().getName();
		List <Integer> myPacketsID = new ArrayList <Integer>();
		List <PersonalizedPacket> myPackets = new ArrayList <PersonalizedPacket>();
		myPackets = em.createNamedQuery(PersonalizedPacket.FIND_ALL, PersonalizedPacket.class).getResultList();
		for(PersonalizedPacket p: myPackets){
			if (p.getUser1().getEmail().equals(id)) myPacketsID.add(p.getPacket());
		}
		return myPacketsID;
	}

	private List<PersonalizedPacket> findAllPersonalizedPacket(){
		return em.createNamedQuery(PersonalizedPacket.FIND_ALL, PersonalizedPacket.class).getResultList();
		
	}
	
	@Override
	public List<String> getPacketAttractions(int id) {
		List<String> someAttractions= new ArrayList<String>();
		List<Attraction> attractions = attractionByPacket(id);
		for(Attraction a: attractions)
			someAttractions.add(a.toString());
		return someAttractions;
	}
	
	@Override
	public List<String> getCityAttractions(int id) {
		List<String> someAttractions= new ArrayList<String>();
		List<Attraction> packetAttractions = attractionByPacket(id);
		List<Attraction> attractions = attractionByCity(getPersonalizedPacket(id).getCity());
		for(Attraction a: attractions)
			if (!packetAttractions.contains(a))someAttractions.add(a.toString());
		return someAttractions;
	}
	
	private List<Attraction> attractionByCity(String city){
		List<Attraction> attractions = new ArrayList<Attraction>();
		List<Attraction> cityAttractions = em.createNamedQuery(Attraction.FIND_ATTRACTION_BY_CITY, Attraction.class).setParameter("city", city).getResultList();
		for (Attraction a: cityAttractions){
			attractions.add(a);
		}
		return attractions;
	}
	
	
	private List<Attraction> attractionByPacket(int id){
		PersonalizedPacket pers = getPersonalizedPacket(id);
		List<Attraction> attractions = new ArrayList<Attraction>();
		List<PacketAttraction> pattractions = pers.getPacketAttractions();
		for (PacketAttraction pa: pattractions){
			if(pa.getPacketBean()==null)
			attractions.add(pa.getAttractionBean());
		}
		return attractions;
	}
	
	@Override
	public List<String> getUserPendingPacket() {
		String id = context.getCallerPrincipal().getName();
		List<String> list = new ArrayList<String>();
		List <PersonalizedPacket> myPackets = findAllPersonalizedPacket();
		for ( PersonalizedPacket p: myPackets)
			if(!p.getConfirmed() && p.getUser1().getEmail().equals(id))
				list.add(p.toString());
		return list;
	}

	@Override
	public List<String> getUserConfirmedPacket() {
		String id = context.getCallerPrincipal().getName();
		List<String> list = new ArrayList<String>();
		List <PersonalizedPacket> myPackets = findAllPersonalizedPacket();
		for ( PersonalizedPacket p: myPackets)
			if(p.getConfirmed() && p.getUser1().getEmail().equals(id))
				list.add(p.toString());
		return list;
	}
	
	@Override 
	public List<String> getReturnFlights(int id){
		List<String> flightList = findFlightByDeparture(getPersonalizedPacket(id).getCity());
		return flightList;
		
	}
	
	@Override 
	public List<String> getDepartureFlights(int id){
		List<String> flightList = findFlightByArrival(getPersonalizedPacket(id).getCity());
		return flightList;
		
	}
	
	
	public List<String> findFlightByDeparture(String city) {
		
		List<Airport> cityAirports = new ArrayList<Airport>();
		List<String> list = new ArrayList<String>();
		
		for(Airport a: airportByCity(city))
			cityAirports.add(a);
		
		for(Airport a: cityAirports){
			for(Flight f: flightByDepartureAirport(a.getName()))
				list.add(f.toString());
		}
		
		return list;
			}
	
	public List<String> findFlightByArrival(String city){
		
		List<Airport> cityAirports = new ArrayList<Airport>();
		List<String> list = new ArrayList<String>();
		
		for(Airport a: airportByCity(city))
			cityAirports.add(a);
		
		for(Airport a: cityAirports){
			for(Flight f: flightByArrivalAirport(a.getName()))
				list.add(f.toString());
		}
		return list;
			}
	
	private List<Flight> flightByDepartureAirport(String airport){
		return em.createNamedQuery(Flight.FIND_FLIGHT_BY_DEPARTURE, Flight.class).setParameter("airport1", airport).getResultList();
	}
	
	private List<Flight> flightByArrivalAirport(String airport){
		return em.createNamedQuery(Flight.FIND_FLIGHT_BY_ARRIVAL, Flight.class).setParameter("airport2", airport).getResultList();
	}
	
	private List<Airport> airportByCity(String city){
		return em.createNamedQuery(Airport.FIND_AIRPORT_BY_CITY, Airport.class).setParameter("city", city).getResultList();
	}
	
	@Override
	public void setPacketDates(int persPackID, Date departure, Date return_){
		PersonalizedPacket pers = em.createNamedQuery(PersonalizedPacket.FIND_PACKET,PersonalizedPacket.class).setParameter("packet",persPackID).getSingleResult();
		pers.setDeparture(departure);
		pers.setReturn_(return_);
		em.merge(pers);
	}

	@Override
	public void confirmPacket(int id, int partecipants) {
		PersonalizedPacket pers = em.createNamedQuery(PersonalizedPacket.FIND_PACKET,PersonalizedPacket.class).setParameter("packet", id).getSingleResult();
		pers.setConfirmed(true);
		pers.setPartecipants(partecipants);
		em.merge(pers);
	}
	
	@Override
	public String searchPersonalizedPacketById(int id){
		PersonalizedPacket p = em.createNamedQuery(PersonalizedPacket.FIND_PACKET, PersonalizedPacket.class).setParameter("packet", id).getSingleResult();
		return p.toString();
	}
	
	@Override
	public void save(int packetID) {
		PersonalizedPacket packet = em.createNamedQuery(PersonalizedPacket.FIND_PACKET, PersonalizedPacket.class)
				.setParameter("packet", packetID).getSingleResult();
		User employee = em.createNamedQuery(User.FIND_BY_MAIL, User.class)
				.setParameter("email", packet.getUser2().getEmail()).getSingleResult();
		User user = em.createNamedQuery(User.FIND_BY_MAIL, User.class)
				.setParameter("email", context.getCallerPrincipal().getName())
				.getSingleResult();
		PersonalizedPacket newPacket = new PersonalizedPacket(packet, user, employee);
		em.persist(newPacket);
		setPersonalizedPacketID(newPacket.getPacket());
		registerFlightp(packetID);
		registerAttractionp(packetID);
	}


		@Override
		public void registerFlightp(int packet) {
			PersonalizedPacket pack = em.createNamedQuery(PersonalizedPacket.FIND_PACKET, PersonalizedPacket.class)
					.setParameter("packet", packet).getSingleResult();
			PersonalizedPacket perspacket = em
					.createNamedQuery(PersonalizedPacket.FIND_PACKET,
							PersonalizedPacket.class)
					.setParameter("packet", personalizedPacketID).getSingleResult();
			List<Flight> packetFlights = new ArrayList<Flight>();
			List<PacketFlight> packf = pack.getPacketFlights();
			for (PacketFlight pf : packf) {
				packetFlights.add(pf.getFlight());
				System.out.println(pf.getFlight().toString());
			}
			for (Flight f : packetFlights) {
				PacketFlight p = new PacketFlight(perspacket, f);
				em.persist(p);
				perspacket.addPacketFlight(p);
			}
	}

	@Override
	public void registerAttractionp(int packet) {
		PersonalizedPacket pack = em.createNamedQuery(PersonalizedPacket.FIND_PACKET, PersonalizedPacket.class)
				.setParameter("packet", packet).getSingleResult();
		PersonalizedPacket perspacket = em
				.createNamedQuery(PersonalizedPacket.FIND_PACKET,
						PersonalizedPacket.class)
				.setParameter("packet", personalizedPacketID).getSingleResult();
		List<Attraction> packetAttractions = new ArrayList<Attraction>();
		List<PacketAttraction> packa = pack.getPacketAttractions();
		for (PacketAttraction pa : packa) {
			packetAttractions.add(pa.getAttractionBean());
			System.out.println(pa.getAttractionBean().toString());
		}
		for (Attraction a : packetAttractions) {
			PacketAttraction p = new PacketAttraction(perspacket, a);
			em.persist(p);
			perspacket.addPacketAttraction(p);
		}
	}

	@Override
	public List<String> getAttractionsFromPacket(int id) {
		PersonalizedPacket p = em.createNamedQuery(PersonalizedPacket.FIND_PACKET, PersonalizedPacket.class).setParameter("packet", id).getSingleResult();
		List<PacketAttraction> pa = p.getPacketAttractions();
		List<String> list = new ArrayList<String>();
		for (PacketAttraction a: pa){
			list.add(a.getAttractionBean().toString());
		}
		return list;
	}

	@Override
	public List<String> getFlightsFromPacket(int id) {
		PersonalizedPacket p = em.createNamedQuery(PersonalizedPacket.FIND_PACKET, PersonalizedPacket.class).setParameter("packet", id).getSingleResult();
		List<PacketFlight> pa = p.getPacketFlights();
		List<String> list = new ArrayList<String>();
		for (PacketFlight a: pa){
			list.add(a.getFlight().toString());
		}
		return list;
	}
	
	@Override public boolean getPacketUser(int id){
		String user = em.createNamedQuery(PersonalizedPacket.FIND_PACKET, PersonalizedPacket.class).setParameter("packet", id).getSingleResult().getUser1().getEmail();
		String caller = context.getCallerPrincipal().getName();
		if (user.equals(caller)) return false;
		else return true;
		
	}
}
